package com.hjh.core.activity

import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import androidx.activity.enableEdgeToEdge
import androidx.annotation.IdRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.viewbinding.ViewBinding
import com.drake.softinput.hideSoftInput
import com.dylanc.viewbinding.base.ActivityBinding
import com.dylanc.viewbinding.base.ActivityBindingDelegate
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.hjh.permission.PermissionUtil

abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity(),
    ActivityBinding<VB> by ActivityBindingDelegate() {


    @IdRes
    private var mainId: Int? = null

    @IdRes
    private var navHostId: Int? = null

    @Suppress("MemberVisibilityCanBePrivate")
    var navController: NavController? = null

    private var navView: BottomNavigationView? = null

    /**
     * A set of Android view ID resources (@IdRes).
     */
    private var bottomViewIdSet: Set<Int>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentViewWithBinding()
        mainId?.let {
            ViewCompat.setOnApplyWindowInsetsListener(findViewById(it)) { v, insets ->
                val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
                v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
                insets
            }
        }

        navHostId?.let {
            val navHost: NavHostFragment =
                supportFragmentManager.findFragmentById(it) as NavHostFragment
            navController = navHost.navController
        }

        navView?.also { view ->
            navController?.also { controller ->
                val appBarConfiguration = bottomViewIdSet?.let(::AppBarConfiguration)
                setupActionBarWithNavController(
                    controller,
                    appBarConfiguration ?: AppBarConfiguration(controller.graph)
                )
                view.setupWithNavController(controller)
            }
        }

        initView()
        initListener()
        initData()
        initObserver()
    }

    override fun onDestroy() {
        release()
        super.onDestroy()
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        if (ev?.action == MotionEvent.ACTION_DOWN) {
            val view = currentFocus
            if (isShouldHideKeyBord(view, ev)) {
                hideSoftInput()
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    override fun onSupportNavigateUp(): Boolean {
        return navController?.navigateUp() == true || super.onSupportNavigateUp()
    }

    /**
     * 初始化视图
     * @param mainId 主布局id
     * @param navHostId 导航布局id
     * @param navView 导航栏
     * @param bottomViewIdSet 导航栏 id 集合
     */
    @Suppress("unused")
    protected fun initResId(
        @IdRes mainId: Int? = null,
        @IdRes navHostId: Int? = null,
        navView: BottomNavigationView? = null,
        bottomViewIdSet: Set<Int>? = null
    ) {
        this.mainId = mainId
        this.navHostId = navHostId
        this.navView = navView
        this.bottomViewIdSet = bottomViewIdSet
    }

    protected open fun initView() {}
    protected open fun initData() {}
    protected open fun initListener() {}
    protected open fun initObserver() {}
    protected open fun release() {}


    /**
     * 判定当前是否需要隐藏
     */
    private fun isShouldHideKeyBord(v: View?, ev: MotionEvent?): Boolean {
        if (v != null && v is EditText && ev != null) {
            val l = intArrayOf(0, 0)
            v.getLocationInWindow(l)
            val left = l[0]
            val top = l[1]
            val bottom = top + v.height
            val right = left + v.width
            return !(ev.x > left && ev.x < right && ev.y > top && ev.y < bottom)
        }
        return false
    }

    /**
     * 统一请求权限方法
     *
     * @param storage       是否请求 Android 11+ 的“所有文件访问权限”
     * @param readStorage   是否请求读外部存储权限（Android 6~10）
     * @param writeStorage  是否请求写外部存储权限（Android 6~10）
     * @param location      是否请求精确位置权限
     * @param backgroundLocation 是否请求后台位置权限（Android 10+）
     * @param camera        是否请求相机权限
     * @param audio         是否请求录音权限
     * @param phoneState    是否请求读取设备状态权限
     * @param phoneNumbers  是否请求读取电话号码权限
     * @param readContacts  是否请求读取联系人权限
     * @param writeContacts 是否请求写联系人权限
     * @param sendSms       是否请求发送短信权限
     * @param receiveSms    是否请求接收短信权限
     * @param readSms       是否请求读取短信权限
     * @param readCalendar  是否请求读取日历权限
     * @param writeCalendar 是否请求写日历权限
     * @param bodySensors   是否请求访问身体传感器权限
     * @param bluetoothScan 是否请求蓝牙扫描权限（Android 12+）
     * @param bluetoothConnect 是否请求蓝牙连接权限（Android 12+）
     * @param postNotifications 是否请求发送通知权限（Android 13+）
     * @param onGranted     所有权限被授予时的回调
     * @param onDenied      部分或全部权限被拒绝时的回调，带有被拒权限列表
     */
    fun requestPermission(
        storage: Boolean = false,
        readStorage: Boolean = false,
        writeStorage: Boolean = false,
        location: Boolean = false,
        backgroundLocation: Boolean = false,
        camera: Boolean = false,
        audio: Boolean = false,
        phoneState: Boolean = false,
        phoneNumbers: Boolean = false,
        readContacts: Boolean = false,
        writeContacts: Boolean = false,
        sendSms: Boolean = false,
        receiveSms: Boolean = false,
        readSms: Boolean = false,
        readCalendar: Boolean = false,
        writeCalendar: Boolean = false,
        bodySensors: Boolean = false,
        bluetoothScan: Boolean = false,
        bluetoothConnect: Boolean = false,
        postNotifications: Boolean = false,
        onGranted: (() -> Unit)? = null,
        onDenied: ((denied: MutableList<String>) -> Unit)? = null
    ) {
        PermissionUtil.request(
            this@BaseActivity,
            storage,
            readStorage,
            writeStorage,
            location,
            backgroundLocation,
            camera,
            audio,
            phoneState,
            phoneNumbers,
            readContacts,
            writeContacts,
            sendSms,
            receiveSms,
            readSms,
            readCalendar,
            writeCalendar,
            bodySensors,
            bluetoothScan,
            bluetoothConnect,
            postNotifications,
            onGranted,
            onDenied
        )
    }
}